#pragma once

#include <iostream>
#include <memory>

#include <list>

#include <algorithm>

#include "Log.hpp"
#include "InetAddr.hpp"
#include "Mutex.hpp"

using namespace LockModule;
using namespace LogModule;

class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendTo(int sockfd, std::string msg) = 0;
    // 每个User将来都要支持区分自己（目前以端口来区分
    virtual bool operator == (const InetAddr &user) = 0;
    // 每个User必须提供自己的身份给外层
    virtual std::string Id() = 0;
};


class User : public UserInterface
{
public:
    User(const InetAddr &id)
        : _id(id)
    {}
    bool operator == (const InetAddr &other_id) // "const" "override" 不能写，因为是纯虚函数 本来就没有实现
    {
        // 转化成 InetAddr 类自己的 operator==实现
        return _id == other_id;
    }
    void SendTo(int sockfd, std::string msg)
    {
        LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << " info: " << msg;
        ssize_t n = sendto(sockfd, msg.c_str(), msg.size(), 0, _id.NetAddr(), _id.NetAddrLen());
        (void)n;
    }
    std::string Id(){return _id.Addr();}
    ~User(){}
private:
    InetAddr _id;
};

class UserManager
{
public:
    UserManager(){}
    bool AddUser(InetAddr &id)
    {
        LockGuard guard(_lock);
        for(auto & user : _users){
            if(*user == id)
            {
                // LOG(LogLevel::DEBUG) << id.Addr() <<"用户已经存在";
                return false;
            }
        }
        LOG(LogLevel::DEBUG) << "已新增用户 " << id.Addr();
        _users.push_back(std::make_shared<User>(id));
        return true;
    }
    void DelUser(InetAddr &id)
    {
        auto pos = std::remove_if(_users.begin(), _users.end(), 
        // user 是UserInterface的指针，以后可以有更多UserInterface的子类可以删除不只是User
        [&id](std::shared_ptr<UserInterface> &user)
        {
            return *user == id;
        });
        _users.erase(pos , _users.end());
    }
    
    void Router(int sockfd, const std::string &msg)
    {
        LockGuard guard(_lock);
        for(auto & user : _users)
        {
            user->SendTo(sockfd, msg);
        }
    }

    ~UserManager(){}
private:
    std::list<std::shared_ptr<UserInterface>> _users;
    Mutex _lock;
};

